#include "SumPrimitive.h"

SumPrimitive::SumPrimitive (QD3DResourcePack *pDataPack,
		QD3DResourcePack *pResultPack,UINT elemNum,
		UINT structSize, const std::string &structBufType) :
		_elemNum (elemNum)
{
	QD3DUtils d3DUtils;

	_pGroupSizeDxConstBuf = d3DUtils.createConstBuffer< ConstVars > ();

	_tempPackPtrs.push_back (pDataPack);
	for (; elemNum > 64; ) {
		elemNum = ceil (elemNum / 64.0);
		ID3D11Buffer *pTempDxBuf = d3DUtils.createStructuredBuffer (
				elemNum, structSize, NULL,
				D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE);
		_tempPackPtrs.push_back (new QD3DResourcePack (pTempDxBuf));
	}
	_tempPackPtrs.push_back (pResultPack);

	QD3DShaderDesc shaderDesc;
	shaderDesc.setDefine ("TYPE", structBufType);
	_p_sumCS = d3DUtils.createShaderFromFile< ID3D11ComputeShader > (
			QD3DUtils::COMPUTE_SHADER, "cs_5_0",
			"..\\Data\\Shaders\\Primitives\\SumCS.hlsl", "csMain", shaderDesc);
}

SumPrimitive::~SumPrimitive ()
{
	SAFE_RELEASE (_pGroupSizeDxConstBuf);
	SAFE_RELEASE (_p_sumCS);
	for (int i = 1; i < _tempPackPtrs.size () - 1; ++i)
		delete _tempPackPtrs[i];
}

void SumPrimitive::run ()
{
	QD3DUtils d3dUtils;
	ConstVars constVars;

	QVector< ID3D11Buffer * > dxConstBufPtrs (1);
	QVector< ID3D11ShaderResourceView * > dxSRVPtrs (1);
	QVector< ID3D11UnorderedAccessView * > dxUAVPtrs (1);

	dxConstBufPtrs[0] = _pGroupSizeDxConstBuf;
	d3dUtils.setConstBufs (QD3DUtils::COMPUTE_SHADER, 0, dxConstBufPtrs);

	d3dUtils.setComputeShader (_p_sumCS);

	for (int totalElemNum = _elemNum, i = 0; totalElemNum > 1;
			totalElemNum = ceil (totalElemNum / 64.0), ++i) {
		constVars.var.totalElemNum = totalElemNum;
		d3dUtils.updateSubresource (_pGroupSizeDxConstBuf, 0, &constVars);
		dxSRVPtrs[0] = _tempPackPtrs[i]->getSRV ();
		d3dUtils.setSRVs (QD3DUtils::COMPUTE_SHADER, 0, dxSRVPtrs);
		dxUAVPtrs[0] = _tempPackPtrs[i + 1]->getUAV ();
		d3dUtils.setUAVs (QD3DUtils::COMPUTE_SHADER, 0, dxUAVPtrs);
		d3dUtils.dispatch (ceil (totalElemNum / 64.0), 1, 1);
		d3dUtils.clearSRVs (QD3DUtils::COMPUTE_SHADER, 0, dxSRVPtrs.size ());
		d3dUtils.clearUAVs (QD3DUtils::COMPUTE_SHADER, 0, dxUAVPtrs.size ());
	}
	d3dUtils.clearConstBufs (QD3DUtils::COMPUTE_SHADER, 0, dxConstBufPtrs.size ());
}